#include "cgzCTcpWS.h"
#include "cgzCTcpGateWC.h"
#include "cgzCThreadPool.h"

cgzCTcpGateWC::cgzCTcpGateWC(
    cgzCThreadPool *pool,
    const char *name,
    const std::string ip,
    const int port,
    const int cid)
    : cgzCTcpWC(pool, name, ip, port, cid)
{
    m_tenum = cgzETask::CTcpGateWC;
}

cgzCTcpGateWC::~cgzCTcpGateWC()
{
}

bool cgzCTcpGateWC::sticking()
{
    // 至少读取一个包头
    int used = m_readCire.used();
    if (used < sizeof(cgzGateHeader))
    {
        return false;
    }

    // 验证一个完整的消息包
    cgzGateHeader header;
    m_readCire.read(&header, sizeof(header));
    if (used < header.all)
    {
        return false;
    }

    // 将包放入队列
    todoret(header);
    return true;
}

bool cgzCTcpGateWC::todoret(cgzGateHeader &header)
{
    // 更改消息目标
    auto it = m_gates.find(header.mid);
    if (it != m_gates.end())
    {
        auto target = it->second;
        auto itt = m_pool->getTask(target);
        if (!itt)
        {
            return false;
        }
        switch (itt->getTEnum())
        {
        case cgzETask::CTcpGateS:
        case cgzETask::CTcpGateWS:
        {
            // 网关收到服务端消息-转发给客户端
            void *node = malloc(sizeof(cgzCSendWS));
            // 构造发送消息
            auto psend = new (node) cgzCSendWS(header.ufd, header.mid, header.len, header.cid);
            // 弹出消息头部
            m_readCire.pop(sizeof(header));
            // 读取消息数据
            void *data = (psend->m_data + sizeof(cgzHeader));
            m_readCire.read(data, header.len);
            m_readCire.pop(header.len);
            // 添加发送任务
            regTask(itt->getName(), psend);
            return true;
        }
        break;
        default:
        {
            // 异常消息
            cgz_this_error("task not found, mid={}", header.mid);
        }
        }
    }
    else
    {
        cgz_this_error("gate not found, mid={}", header.mid);
        return true;
    }
    return true;
}

bool cgzCTcpGateWC::run(cgzCLoopC *task)
{
    switch (task->getEType())
    {
    case ETCP_C::TCPC_GADD:
    {
        auto &map = static_cast<cgzCGAddC *>(task)->map;
        m_gates.insert(map.begin(), map.end());
    }
    break;
    case ETCP_C::TCPC_GDEL:
    {
        auto &set = static_cast<cgzCGDelC *>(task)->set;
        for (auto it : set)
        {
            auto eit = m_gates.find(it);
            if (eit != m_gates.end())
            {
                m_gates.erase(eit);
            }
        }
    }
    break;
    case ETCP_C::TCPC_GCLR:
    {
        m_gates.clear();
    }
    break;
    default:
    {
        assert(false);
    }
    }
    task->~cgzCLoopC();
    free(task);
    return true;
}